package com.xzx.framework.util.http;

import net.sf.json.JSONObject;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.Cookie;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author yuwei,jack.zeng
 * @time 2015-10-15上午09:23:10
 */
public abstract class HttpUtil {
	public static String doGet(String url, Map<String, String> params) {
		return doGet(url, params, String.class);
	}

	public static String doGet(String url, Map<String, String> params, List<Cookie> cookieList) {
		return doGet(url, params, cookieList, String.class);
	}

	public static <T> T doGet(String url, Map<String, String> params, Class<T> clz) {
		return doGet(url, params, null, clz);
	}

	public static <T> T doGet(String url, Map<String, String> params, List<Cookie> cookieList, Class<T> clz) {
		URIBuilder uriBuilder = null;

		try {
			uriBuilder = new URIBuilder(url);
			if (params != null) {
				for (Entry<String, String> e : params.entrySet()) {
					String v = e.getValue();
					if (v == null) {
						continue;
					}
					uriBuilder.setParameter(e.getKey(), v);
				}
			}

			URI uri = uriBuilder.build();
			System.out.println(uri);
			return execute0(new HttpGet(uri), cookieList, clz);
		} catch (URISyntaxException e) {
			return null;
		}
	}

	public static String doPost(String url, Map<String, String> params) {
		return doPost(url, params, String.class);
	}

	public static String doPost(String url, Map<String, String> params, List<Cookie> cookieList) {
		return doPost(url, params, cookieList, String.class);
	}

	public static <T> T doPost(String url, Map<String, String> params, Class<T> clz) {
		return doPost(url, params, null, clz);
	}

	public static <T> T doPost(String url, Map<String, String> params, List<Cookie> cookieList, Class<T> clz) {
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		if (params != null) {
			for (Entry<String, String> e : params.entrySet()) {
				String v = e.getValue();
				if (v == null) {
					continue;
				}
				list.add(new BasicNameValuePair(e.getKey(), v));
			}
		}

		HttpPost post = new HttpPost(url);
		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, Consts.UTF_8);
		post.setEntity(entity);

		return execute0(post, cookieList, clz);
	}

	public static String doPut(String url, Map<String, String> params) {
		return doPut(url, params, String.class);
	}

	public static String doPut(String url, Map<String, String> params, List<Cookie> cookieList) {
		return doPut(url, params, cookieList, String.class);
	}

	public static <T> T doPut(String url, Map<String, String> params, Class<T> clz) {
		return doPut(url, params, null, clz);
	}

	public static <T> T doPut(String url, Map<String, String> params, List<Cookie> cookieList, Class<T> clz) {
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		if (params != null) {
			for (Entry<String, String> e : params.entrySet()) {
				String v = e.getValue();
				if (v == null) {
					continue;
				}
				list.add(new BasicNameValuePair(e.getKey(), v));
			}
		}

		HttpPut put = new HttpPut(url);
		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, Consts.UTF_8);
		put.setEntity(entity);
		return execute0(put, cookieList, clz);
	}

	public static String doDelete(String url, Map<String, String> params) {
		return doDelete(url, params, String.class);
	}

	public static String doDelete(String url, Map<String, String> params, List<Cookie> cookieList) {
		return doDelete(url, params, cookieList, String.class);
	}

	public static <T> T doDelete(String url, Map<String, String> params, Class<T> clz) {
		return doDelete(url, params, null, clz);
	}

	public static <T> T doDelete(String url, Map<String, String> params, List<Cookie> cookieList, Class<T> clz) {
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		if (params != null) {
			for (Entry<String, String> e : params.entrySet()) {
				String v = e.getValue();
				if (v == null) {
					continue;
				}
				list.add(new BasicNameValuePair(e.getKey(), v));
			}
		}

		HttpDelete del = new HttpDelete(url);
		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, Consts.UTF_8);
		del.setEntity(entity);
		return execute0(del, cookieList, clz);
	}

	public static String execute(String url, Map<String, String> params, String method) {
		return execute(url, params, method, String.class);
	}

	public static String execute(String url, Map<String, String> params, String method, List<Cookie> cookieList) {
		return execute(url, params, method, cookieList, String.class);
	}

	public static <T> T execute(String url, Map<String, String> params, String method, Class<T> clz) {
		return execute(url, params, method, null, clz);
	}

	public static <T> T execute(String url, Map<String, String> params, String method, List<Cookie> cookieList, Class<T> clz) {
		if (method == null || method.trim().equals("")) {
			return doGet(url, params, cookieList, clz);
		}

		method = method.trim();

		if (method.equalsIgnoreCase("get")) {
			return doGet(url, params, cookieList, clz);
		}
		if (method.equalsIgnoreCase("post")) {
			return doPost(url, params, cookieList, clz);
		}
		if (method.equalsIgnoreCase("put")) {
			return doPut(url, params, cookieList, clz);
		}
		if (method.equalsIgnoreCase("delete")) {
			return doDelete(url, params, cookieList, clz);
		}

		return doPost(url, params, cookieList, clz);
	}

	/**
	 * 以json格式传送参数，post访问
	 * 
	 * @param url
	 * @param jsonParam
	 * @return
	 **/
	public static String doPostJson(String url, String jsonParam) {
		return doPostJson(url, jsonParam, String.class);
	}

	/**
	 * 以json格式传送参数，post访问
	 * 
	 * @param url
	 * @param jsonParam
	 * @param cookieList
	 * @return
	 **/
	public static String doPostJson(String url, String jsonParam, List<Cookie> cookieList) {
		return doPostJson(url, jsonParam, cookieList, String.class);
	}

	/**
	 * 以json格式传送参数，post访问
	 * 
	 * @param url
	 * @param jsonParam
	 * @param clz
	 * @return
	 **/
	public static <T> T doPostJson(String url, String jsonParam, Class<T> clz) {
		return doPostJson(url, jsonParam, null, clz);
	}

	/**
	 * 以json格式传送参数，post访问
	 * 
	 * @param url
	 * @param jsonParam
	 * @param cookieList
	 * @param clz
	 * @return
	 **/
	public static <T> T doPostJson(String url, String jsonParam, List<Cookie> cookieList, Class<T> clz) {
		try {
			// String encoderJson = URLEncoder.encode(jsonParam,
			// Consts.UTF_8.toString());
			HttpPost post = new HttpPost(url);
			post.addHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8");
			StringEntity se = new StringEntity(jsonParam);
			se.setContentType("text/json;charset=UTF-8");
			se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8"));
			post.setEntity(se);
			return execute0(post, cookieList, clz);
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}

	/**
	 * post方式上传文件
	 * 
	 * @param url
	 * @param bytes
	 * @param fieldName
	 *            服务器端接收文件的参数名
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static String upload(String url, byte[] bytes, String fieldName, String fileName) {
		return upload(url, bytes, fieldName, fileName, null);
	}

	/**
	 * post方式上传文件
	 * 
	 * @param url
	 * @param bytes
	 * @param fieldName
	 *            服务器端接收文件的参数名
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static String upload(String url, byte[] bytes, String fieldName, String fileName, Map<String, String> params) {
		return upload(url, bytes, fieldName, fileName, params, String.class);
	}

	/**
	 * post方式上传文件
	 * 
	 * @param url
	 * @param bytes
	 * @param fieldName
	 *            服务器端接收文件的参数名
	 * @param fileName
	 *            文件名
	 * @param clz
	 * @return
	 */
	public static <T> T upload(String url, byte[] bytes, String fieldName, String fileName, Map<String, String> params, Class<T> clz) {
		return upload(url, bytes, fieldName, fileName, params, null, clz);
	}

	/**
	 * post方式上传文件
	 * 
	 * @param url
	 * @param bytes
	 * @param fieldName
	 *            服务器端接收文件的参数名
	 * @param fileName
	 *            文件名
	 * @param cookieList
	 * @param clz
	 * @return
	 */
	public static <T> T upload(String url, byte[] bytes, String fieldName, String fileName, Map<String, String> params, List<Cookie> cookieList, Class<T> clz) {
		HttpPost post = new HttpPost(url);
		ByteArrayBody fbody = new ByteArrayBody(bytes, ContentType.DEFAULT_BINARY, fileName);

		MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE).setCharset(Consts.UTF_8);
		builder.addPart(fieldName, fbody);
		if (params != null && !params.isEmpty()) {
			for (Entry<String, String> e : params.entrySet()) {
				String v = e.getValue();
				if (v == null) {
					continue;
				}
				builder.addTextBody(e.getKey(), v);
			}
		}

		HttpEntity entity = builder.build();
		post.setEntity(entity);
		return execute0(post, cookieList, clz);
	}

	@SuppressWarnings("unchecked")
	private static <T> T execute0(HttpUriRequest request, List<Cookie> cookieList, Class<T> clz) {
		if (cookieList != null && cookieList.size() > 0) {
			StringBuffer buf = new StringBuffer("");
			for (Cookie cookie : cookieList) {
				buf.append(cookie.getName()).append("=").append(cookie.getValue()).append(";");
			}
			buf.deleteCharAt(buf.length() - 1);
			request.addHeader("Cookie", buf.toString());
		}

		CloseableHttpClient client = HttpClients.custom().build();
		HttpClientContext context = HttpClientContext.create();

		try {
			return (T) client.execute(request, new ResponseHandler(clz), context);
		} catch (Exception e) {
			throw new HttpException(e.getLocalizedMessage());
		}finally {
			try {
				client.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = {new MyX509TrustManager()};
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();

			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			jsonObject = JSONObject.fromObject(buffer.toString());
		} catch (ConnectException ce) {
			ce.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jsonObject;
	}

	public static class MyX509TrustManager implements X509TrustManager {

		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			// TODO Auto-generated method stub
			
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			// TODO Auto-generated method stub
			
		}

		public X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return null;
		}

	}
}
